使用kubeadm在Rocky linux上安装k8s集群
实验环境
角色 | IP | 主机名 | containerd版本 | 硬件配置 | 系统 | 内核 | 安装组件 |
---|---|---|---|---|---|---|---|
master | 10.0.0.10 | k8s-master | 1.7.17 | 2c4g | Rocky Linux release 9.3 (Blue Onyx) | 5.14.0-362.8.1.el9_3.aarch64 | kube-apiserver,kube-controller-manager,kube-scheduler,kubelet,etcd |
Node01 | 10.0.0.100 | K8s-node01 | 1.7.17 | 4c8g | Rocky Linux release 9.3 (Blue Onyx) | 5.14.0-362.8.1.el9_3.aarch64 | kubelet,kube-proxy,containerd,etcd |
node02 | 10.0.0.101 | k8s-node02 | 1.7.17 | 4c8g | Rocky Linux release 9.3 (Blue Onyx) | 5.14.0-362.8.1.el9_3.aarch64 | kubelet,kube-proxy,containerd,etcd |
node03 | 10.0.0.102 | k8s-node03 | 1.7.17 | 2c4g | Rocky Linux release 9.3 (Blue Onyx) | 5.14.0-362.8.1.el9_3.aarch64 | kubelet,kube-proxy,containerd,etcd |
准备开始
- 一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux 发行版以及一些不提供包管理器的发行版提供通用的指令。
- 每台机器 2 GB 或更多的 RAM(如果少于这个数字将会影响你应用的运行内存)。
- CPU 2 核心及以上。
- 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)。
- 节点之中不可以有重复的主机名、MAC 地址或 product_uuid。请参见这里了解更多详细信息。
- 开启机器上的某些端口。请参见这里了解更多详细信息。
- 交换分区的配置。kubelet 的默认行为是在节点上检测到交换内存时无法启动。 kubelet 自 v1.22 起已开始支持交换分区。自 v1.28 起,仅针对 cgroup v2 支持交换分区; kubelet 的 NodeSwap 特性门控处于 Beta 阶段,但默认被禁用。
- 如果 kubelet 未被正确配置使用交换分区,则你必须禁用交换分区。 例如,
sudo swapoff -a
将暂时禁用交换分区。要使此更改在重启后保持不变,请确保在如/etc/fstab
、systemd.swap
等配置文件中禁用交换分区,具体取决于你的系统如何配置。
- 如果 kubelet 未被正确配置使用交换分区,则你必须禁用交换分区。 例如,
kubeadm
的安装是通过使用动态链接的二进制文件完成的,安装时假设你的目标系统提供 glibc
。 这个假设在许多 Linux 发行版(包括 Debian、Ubuntu、Fedora、CentOS 等)上是合理的, 但对于不包含默认 glibc
的自定义和轻量级发行版(如 Alpine Linux),情况并非总是如此。 预期的情况是,发行版要么包含 glibc
, 要么提供了一个兼容层以提供所需的符号。
确保每个节点上 MAC 地址和 product_uuid 的唯一性
- 你可以使用命令
ip link
或ifconfig -a
来获取网络接口的 MAC 地址 - 可以使用
sudo cat /sys/class/dmi/id/product_uuid
命令对 product_uuid 校验
一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。 Kubernetes 使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装失败。
检查网络适配器
如果你有一个以上的网络适配器,同时你的 Kubernetes 组件通过默认路由不可达,我们建议你预先添加 IP 路由规则, 这样 Kubernetes 集群就可以通过对应的适配器完成连接。
检查所需端口
启用这些必要的端口后才能使 Kubernetes 的各组件相互通信。 可以使用 netcat 之类的工具来检查端口是否开放,例如:
nc 127.0.0.1 6443 -v
你使用的 Pod 网络插件 (详见后续章节) 也可能需要开启某些特定端口。 由于各个 Pod 网络插件的功能都有所不同,请参阅他们各自文档中对端口的要求。
master节点需要启用的端口
协议 | 方向 | 端口范围 | 目的 | 使用者 |
---|---|---|---|---|
TCP | 入站 | 6443 | Kubernetes API 服务器 | 所有 |
TCP | 入站 | 2379-2380 | etcd 服务器客户端 API | kube-apiserver、etcd |
TCP | 入站 | 10250 | kubelet API | 自身、控制面 |
TCP | 入站 | 10259 | kube-scheduler | 自身 |
TCP | 入站 | 10257 | kube-controller-manager | 自身 |
node节点需要启用的端口
协议 | 方向 | 端口范围 | 目的 | 使用者 |
---|---|---|---|---|
TCP | 入站 | 10250 | kubelet API | 自身、控制面 |
TCP | 入站 | 10256 | kube-proxy | 自身、负载均衡器 |
TCP | 入站 | 30000-32767 | NodePort Services† | 所有 |
安装容器运行时
为了在 Pod 中运行容器,Kubernetes 使用 容器运行时(Container Runtime)。
默认情况下,Kubernetes 使用 容器运行时接口(Container Runtime Interface,CRI) 来与你所选择的容器运行时交互。
如果你不指定运行时,kubeadm 会自动尝试通过扫描已知的端点列表来检测已安装的容器运行时。
如果检测到有多个或者没有容器运行时,kubeadm 将抛出一个错误并要求你指定一个想要使用的运行时。
参阅 容器运行时 以了解更多信息。
Docker Engine 没有实现 CRI, 而这是容器运行时在 Kubernetes 中工作所需要的。 为此,必须安装一个额外的服务 cri-dockerd。 cri-dockerd 是一个基于传统的内置 Docker 引擎支持的项目, 它在 1.24 版本从 kubelet 中移除。
下面的表格包括被支持的操作系统的已知端点。
运行时 | Unix 域套接字 |
---|---|
containerd | unix:///var/run/containerd/containerd.sock |
CRI-O | unix:///var/run/crio/crio.sock |
Docker Engine(使用 cri-dockerd) | unix:///var/run/cri-dockerd.sock |
容器运行时类型
安装和配置先决条件
启用 IPv4 数据包转发
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
使用以下命令验证 net.ipv4.ip_forward
是否设置为 1:
sysctl net.ipv4.ip_forward
cgroup 驱动
在 Linux 上,控制组(CGroup)用于限制分配给进程的资源。
kubelet 和底层容器运行时都需要对接控制组来强制执行 为 Pod 和容器管理资源 并为诸如 CPU、内存这类资源设置请求和限制。 若要对接控制组,kubelet 和容器运行时需要使用一个 cgroup 驱动。 关键的一点是 kubelet 和容器运行时需使用相同的 cgroup 驱动并且采用相同的配置。
可用的 cgroup 驱动有两个:
cgroupfs 驱动
cgroupfs
驱动是 kubelet 中默认的 cgroup 驱动。 当使用 cgroupfs
驱动时, kubelet 和容器运行时将直接对接 cgroup 文件系统来配置 cgroup。
当 systemd 是初始化系统时, 不 推荐使用 cgroupfs
驱动,因为 systemd 期望系统上只有一个 cgroup 管理器。 此外,如果你使用 cgroup v2, 则应用 systemd
cgroup 驱动取代 cgroupfs
。
systemd cgroup 驱动
当某个 Linux 系统发行版使用 systemd 作为其初始化系统时,初始化进程会生成并使用一个 root 控制组(cgroup
),并充当 cgroup 管理器。
systemd 与 cgroup 集成紧密,并将为每个 systemd 单元分配一个 cgroup。 因此,如果你 systemd
用作初始化系统,同时使用 cgroupfs
驱动,则系统中会存在两个不同的 cgroup 管理器。
同时存在两个 cgroup 管理器将造成系统中针对可用的资源和使用中的资源出现两个视图。某些情况下, 将 kubelet 和容器运行时配置为使用 cgroupfs
、但为剩余的进程使用 systemd
的那些节点将在资源压力增大时变得不稳定。
当 systemd 是选定的初始化系统时,缓解这个不稳定问题的方法是针对 kubelet 和容器运行时将 systemd
用作 cgroup 驱动。
要将 systemd
设置为 cgroup 驱动,需编辑 KubeletConfiguration
的 cgroupDriver
选项,并将其设置为 systemd
。例如:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
...
cgroupDriver: systemd
从 v1.22 开始,在使用 kubeadm 创建集群时,如果用户没有在 KubeletConfiguration
下设置 cgroupDriver
字段 ,kubeadm 默认使用 systemd
。
在 Kubernetes v1.28 中,启用 KubeletCgroupDriverFromCRI
特性门控结合支持 RuntimeConfig
CRI RPC 的容器运行时,kubelet 会自动从运行时检测适当的 Cgroup 驱动程序,并忽略 kubelet 配置中的 cgroupDriver
设置。
如果你将 systemd
配置为 kubelet 的 cgroup 驱动,你也必须将 systemd
配置为容器运行时的 cgroup 驱动。参阅容器运行时文档,了解指示说明。例如:
更改已加入集群的节点的 cgroup 驱动是一项敏感的操作。 如果 kubelet 已经使用某 cgroup 驱动的语义创建了 Pod,更改运行时以使用别的 cgroup 驱动,当为现有 Pod 重新创建 PodSandbox 时会产生错误。 重启 kubelet 也可能无法解决此类问题。
如果你有切实可行的自动化方案,使用其他已更新配置的节点来替换该节点, 或者使用自动化方案 来重新安装。
安装containerd
安装containerd
从v1.6版本开始,捆绑包 cri-containerd-*.tar.gz
已经被弃用,并且会在v2.0版本删除,这里有 官方说明
- 1.x
- 2.x
下载安装包
export CONTAINERD_VERSION=1.7.17
export ARCHITECTURE=arm64
wget https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-linux-${ARCHITECTURE}.tar.gz
压缩包内容如下
$ tar tf containerd-${CONTAINERD_VERSION}-linux-${ARCHITECTURE}.tar.gz
bin/
bin/containerd-shim
bin/containerd-stress
bin/ctr
bin/containerd-shim-runc-v2
bin/containerd-shim-runc-v1
bin/containerd
下载安装包
export CONTAINERD_VERSION=2.0.0
export ARCHITECTURE=arm64
wget https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-linux-${ARCHITECTURE}.tar.gz
压缩包内容如下
$ tar tf containerd-${CONTAINERD_VERSION}-linux-${ARCHITECTURE}.tar.gz
bin/
bin/containerd
bin/ctr
bin/containerd-stress
bin/containerd-shim-runc-v2
解压缩
tar Cxzvf /usr/local containerd-${CONTAINERD_VERSION}-linux-${ARCHITECTURE}.tar.gz
使用systemd管理containerd
下载文件
curl https://raw.githubusercontent.com/containerd/containerd/main/containerd.service -o /usr/lib/systemd/system/containerd.service
containerd.service
文件内容如下
# Copyright The containerd Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
重新加载 systemd 的配置并设置containerd服务开机自启
systemctl daemon-reload
systemctl enable --now containerd
安装runc
下载安装包
export RUNC_VERSION=1.2.1
export ARCHITECTURE=arm64
wget https://github.com/opencontainers/runc/releases/download/v${RUNC_VERSION}/runc.${ARCHITECTURE}
安装
install -m 755 runc.${ARCHITECTURE} /usr/local/sbin/runc
验证
$ runc -v
runc version 1.2.1
commit: v1.2.1-0-gd7735e38
spec: 1.2.0
go: go1.22.8
libseccomp: 2.5.5